﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Nature.Toolkit.GKin
{
    public class AH2004CombustionSuitFactory : ICombustionSuitFactory
    {
        public IIdealGasMixtureTimeController CreateUVAutoIgnitionController()
        {
            return new AH2004UVAutoIgnitionStatePostUpdateChemReactorController();
        }
    }

    class AH2004UVAutoIgnitionStatePostUpdateChemReactorController : SoneStatePostUpdateChemReactorController
    {
        private readonly IdealGasMixtureUVTemperatureTransform 
            StatePostUpdateTransform = new IdealGasMixtureUVTemperatureTransform();
        private double m_speciesAbsDXStep = 1.0e-12;
        private double m_mixtureAbsDTStep = 1.0e-2;
        private double m_mixtureRelDTStep = 1.0e-8;
        private const double SpeciesAbsDXStepMax = 1.0e-5;
        private const double MixtureAbsDTStepMax = 1.0e+2;
        private const double MixtureRelDTStepMax = 1.0e-3;
        

        public AH2004UVAutoIgnitionStatePostUpdateChemReactorController()
        {
            ProposeNextTimeIncrement(1.0e-12);
        }

        protected override double AdvanceChemicalComposition()
        {
            StatePostUpdateTransform.TemperatureInitialEstimation = Mixture.Temperature;
            return base.AdvanceChemicalComposition();
        }

        protected override void Reset()
        {
            base.Reset();
            ProposeNextTimeIncrement(1.0e-12);
            StatePostUpdateTransform.SetBaseState(Mixture);
        }       


        protected override bool ValidateStateChange()
        {
            double absDT = Math.Abs(Mixture.Temperature - MixtureSavePoint.Temperature);
            double relDT = absDT / Mixture.Temperature;            
            return (absDT < 1.0) || (relDT < 1.0e-3);
        }

        protected override void OnStepComplete()
        {
            ProposeNextTimeIncrement(1.0);
            m_mixtureAbsDTStep = Math.Min(MixtureAbsDTStepMax, m_mixtureAbsDTStep * 1.01);
            m_speciesAbsDXStep = Math.Min(SpeciesAbsDXStepMax, m_speciesAbsDXStep * 1.01);
            m_mixtureRelDTStep = Math.Min(MixtureRelDTStepMax, m_mixtureRelDTStep * 1.01);

            double damping;
            damping = m_mixtureAbsDTStep / (MixtureAbsDT + 1.0e-3);
            ProposeNextTimeIncrement(LastTimeIncrement * damping);

            damping = m_mixtureRelDTStep / (MixtureRelDT + 1.0e-10);
            ProposeNextTimeIncrement(LastTimeIncrement * damping);

            damping = m_speciesAbsDXStep / (SpeciesAbsDX + 1.0e-20);
            ProposeNextTimeIncrement(LastTimeIncrement * 1.0e-4 / SpeciesAbsDX);            
        }

        protected override IIdealGasMixtureTransform GetStatePostUpdateTransform()
        {
            return StatePostUpdateTransform;
        }

        protected override IdealGasMixtureTimeController Clone()
        {
            return new AH2004UVAutoIgnitionStatePostUpdateChemReactorController();
        }
    }
}
